package me.itsoo.artemis.framework.core.util;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import me.itsoo.artemis.framework.core.tuple.Pair;
import me.itsoo.artemis.framework.core.tuple.TrimedStringPair;
import org.slf4j.helpers.MessageFormatter;

import java.util.Collection;

/**
 * StringUtils
 *
 * @author zxy
 * @version 0.0.1
 * @since 2023/5/10
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class StringUtils {

    /**
     * 默认占位符
     */
    public static final String PLACEHOLDER = "{}";

    /**
     * 空字符串
     */
    public static final String EMPTY_RESULT = "";

    /**
     * 字符串为空
     *
     * @param cs 源字符串
     * @return boolean
     */
    public static boolean isEmpty(CharSequence cs) {
        return (cs == null) || (cs.length() == 0);
    }

    /**
     * 字符串不为空
     *
     * @param cs 源字符串
     * @return boolean
     */
    public static boolean isNotEmpty(CharSequence cs) {
        return !isEmpty(cs);
    }

    /**
     * 字符串为空白
     *
     * @param cs 源字符串
     * @return boolean
     */
    public static boolean isBlank(CharSequence cs) {
        if (isEmpty(cs)) {
            return true;
        }

        for (int i = 0, len = cs.length(); i < len; ++i) {
            if (!Character.isWhitespace(cs.charAt(i))) {
                return false;
            }
        }

        return true;
    }

    /**
     * 字符串不为空白
     *
     * @param str 源字符串
     * @return boolean
     */
    public static boolean isNotBlank(CharSequence str) {
        return !isBlank(str);
    }

    /**
     * 如果为空白则返回默认值
     *
     * @param cs        CharSequence
     * @param defaultCs CharSequence
     * @param <T>       T
     * @return T
     */
    public static <T extends CharSequence> T defaultIfBlank(T cs, T defaultCs) {
        return isBlank(cs) ? defaultCs : cs;
    }

    /**
     * 如果为空则返回默认值
     *
     * @param cs        CharSequence
     * @param defaultCs CharSequence
     * @param <T>       T
     * @return T
     */
    public static <T extends CharSequence> T defaultIfEmpty(T cs, T defaultCs) {
        return isEmpty(cs) ? defaultCs : cs;
    }

    /**
     * 替换字符串
     *
     * @param str        源字符串
     * @param oldPattern 老内容
     * @param newPattern 新内容
     * @return String
     */
    public static String replace(String str, String oldPattern, String newPattern) {
        if (isBlank(str) || isBlank(oldPattern) || newPattern == null) {
            return str;
        }

        int i = str.indexOf(oldPattern);
        if (i == -1) {
            return str;
        }

        int capacity = str.length();
        if (newPattern.length() > oldPattern.length()) {
            capacity += 16;
        }

        final StringBuilder result = new StringBuilder(capacity);
        int j = 0;
        for (int length = oldPattern.length(); i >= 0; i = str.indexOf(oldPattern, j)) {
            result.append(str, j, i);
            result.append(newPattern);
            j = i + length;
        }

        result.append(str.substring(j));
        return result.toString();
    }

    /**
     * 分割字符串
     *
     * @param str       源字符串
     * @param delimiter 分割字符串
     * @return Pair
     */
    public static Pair<String, String> split(String str, String delimiter) {
        if (isBlank(str) || isBlank(delimiter)) {
            return TrimedStringPair.empty();
        }

        final int i = str.indexOf(delimiter);
        if (i == -1) {
            return TrimedStringPair.empty();
        }

        final String key = str.substring(0, i);
        final String value = str.substring(i + delimiter.length());
        return TrimedStringPair.create(key, value);
    }

    /**
     * 格式化字符串
     *
     * @param tplStr 模板
     * @param args   参数
     * @return String
     */
    public static String format(String tplStr, Object... args) {
        if (tplStr == null) {
            return null;
        }

        if (isBlank(tplStr)) {
            return EMPTY_RESULT;
        }

        if (!tplStr.contains(PLACEHOLDER)) {
            return tplStr;
        }

        return MessageFormatter.arrayFormat(tplStr, args).getMessage();
    }

    /**
     * 源字符串是否包含目标字符串
     *
     * @param str     源字符串
     * @param findStr 目标字符串
     * @return boolean
     */
    public static boolean contains(String str, String findStr) {
        final int i = str.indexOf(findStr);
        if (i == -1) {
            return false;
        }

        // 先寻找左边界
        final boolean findFirst = (i == 0) || (str.charAt(i - 1) == ',');
        if (!findFirst) {
            return false;
        }

        // 再寻找右边界
        final int last = i + findStr.length();
        if (last > str.length()) {
            return false;
        }

        return (last == str.length()) || (str.charAt(last) == ',');
    }

    /**
     * 源字符串是否包含目标字符串
     *
     * @param str         源字符串
     * @param findStrColl 目标字符串
     * @return boolean
     */
    public static boolean containsAll(String str, Collection<String> findStrColl) {
        return findStrColl.stream().anyMatch(t -> contains(str, t));
    }

    /**
     * 首字母大写
     *
     * @param str 源字符串
     * @return String
     */
    public static String upperFirstLetter(String str) {
        if (isBlank(str)) {
            return str;
        }

        char letter = str.charAt(0);
        if (letter >= 'a' && letter <= 'z') {
            letter = (char) (letter - 32);
        }

        return letter + (str.length() > 1 ? str.substring(1) : EMPTY_RESULT);
    }

    /**
     * 首字母小写
     *
     * @param str 源字符串
     * @return String
     */
    public static String lowerFirstLetter(String str) {
        if (isBlank(str)) {
            return str;
        }

        char letter = str.charAt(0);
        if (letter >= 'A' && letter <= 'Z') {
            letter = (char) (letter + 32);
        }

        return letter + (str.length() > 1 ? str.substring(1) : EMPTY_RESULT);
    }

    /**
     * 去掉开头的字符
     *
     * @param str    源字符串
     * @param letter 目标字符
     * @return String
     */
    public static String trimLeadingLetter(String str, char letter) {
        if (isBlank(str)) {
            return null;
        }

        int i;
        for (i = 0; i < str.length() && str.charAt(i) == letter; ++i) {
            // NOP
        }

        return str.substring(i);
    }

    /**
     * 去掉结尾的字符
     *
     * @param str    源字符串
     * @param letter 目标字符
     * @return String
     */
    public static String trimTrailingLetter(String str, char letter) {
        if (isBlank(str)) {
            return null;
        }

        int i;
        for (i = str.length() - 1; i >= 0 && str.charAt(i) == letter; --i) {
            // NOP
        }

        return str.substring(0, i + 1);
    }

    /**
     * 查找共多少个子字符串
     *
     * @param str    源字符串
     * @param subStr 子字符串
     * @return int
     */
    public static int findSubstringCount(String str, String subStr) {
        if (!isBlank(str) && !isBlank(subStr)) {
            int count = 0;
            int i;
            for (int j = 0; (i = str.indexOf(subStr, j)) != -1; j = i + subStr.length()) {
                ++count;
            }

            return count;
        }

        return 0;
    }

    /**
     * 当不为给定前缀时，拼接给前缀
     *
     * @param str    源字符串
     * @param prefix 前缀
     * @return String
     */
    public static String appendWithoutPrefix(String str, String prefix) {
        if (isBlank(str)) {
            return EMPTY_RESULT;
        }

        if (str.startsWith(prefix)) {
            return str;
        }

        return (prefix + str);
    }
}
